Skip to content

feat(ci): add cross-platform final build checks#279

Open
konard wants to merge 3 commits into
ProverCoderAI:mainfrom
konard:issue-278-d92a50df7e27
Open

feat(ci): add cross-platform final build checks#279
konard wants to merge 3 commits into
ProverCoderAI:mainfrom
konard:issue-278-d92a50df7e27

Conversation

@konard
Copy link
Copy Markdown
Contributor

@konard konard commented May 12, 2026

Summary

  • Adds a Final Build GitHub Actions workflow for Ubuntu, macOS, and Windows that builds both packages, smoke-tests both CLIs, and uploads package tarballs.
  • Makes setup/package scripts cross-platform by removing shell-only script wrappers and replacing raw chmod with a Bun helper.
  • Bounds clone-cache mirror refreshes to branch and tag refs so CI does not fetch hosted forge PR refs during cache reuse.

Reproduction and Verification

  • Reproduced the package-script portability gap with packages/app/tests/docker-git/package-scripts-cross-platform.test.ts before implementing the script changes.
  • Reproduced the clone-cache CI failure mode from run 25728183189: E2E (Clone cache) timed out after 1800s on the second cache reuse case while refreshing broad refs/*.
  • Added a regression test in packages/lib/tests/core/templates.test.ts proving mirror refreshes include refs/heads/* and refs/tags/* but not broad refs/*.

Local Checks

  • bun run --cwd packages/lib test -- tests/core/templates.test.ts
  • bun run --cwd packages/app test -- tests/docker-git/package-scripts-cross-platform.test.ts
  • bun run build
  • bun run typecheck
  • bun run lint
  • bun run lint:effect
  • bun run check:dist-deps-prune
  • bun run test
  • git diff --check

Mathematical Guarantees

Invariants

  • forall os in {linux, macos, windows}: final-build(os) -> build(os) and cli_help(app, os) and cli_help(session_sync, os)
  • forall r in clone_cache_refresh_refs: r in refs/heads/* union refs/tags/*
  • forall npm_script in checked_scripts: not contains(npm_script, "bash -lc")

Preconditions

  • Bun and Node versions are provided by the shared setup action.
  • Generated dist artifacts exist before package smoke checks.

Postconditions

  • Package tarballs are produced on each matrix OS.
  • Clone-cache refresh no longer requests refs/pull/* or refs/merge-requests/* through broad refs/*.

Complexity

  • Clone-cache refresh changes from O(|all remote refs|) to O(|heads| + |tags|).

SOURCE: n/a

Fixes #278

konard added 2 commits May 12, 2026 09:48
Adding .gitkeep for PR creation (default mode).
This file will be removed when the task is complete.

Issue: ProverCoderAI#278
@konard konard changed the title [WIP] Надо сделать что бы запускалось как на виндоус так и на линукс удобно. feat(ci): add cross-platform final build checks May 12, 2026
@konard konard marked this pull request as ready for review May 12, 2026 10:20
@konard
Copy link
Copy Markdown
Contributor Author

konard commented May 12, 2026

Working session summary

Done. Updated existing PR 279 and marked it ready:

#279

Implemented:

  • Added cross-platform Final Build workflow for Ubuntu, macOS, and Windows.
  • Removed Unix-only script assumptions from package scripts.
  • Added executable marking helper with Windows no-op behavior.
  • Fixed clone-cache mirror refresh to fetch only heads/tags instead of all refs.
  • Added regression tests for cross-platform scripts and clone-cache refspec invariants.

Verified locally:
build, typecheck, lint, lint:effect, check:dist-deps-prune, full test, targeted regression tests, and git diff --check.

Verified CI on latest SHA a872a79230edcea7405200a732154568f2051d81:
Check, Final Build, Snapshot, and Checking Dependencies all passed. Working tree is clean.

SOURCE: n/a.


This summary was automatically extracted from the AI working session output.

@konard
Copy link
Copy Markdown
Contributor Author

konard commented May 12, 2026

🤖 Solution Draft Log

This log file contains the complete execution trace of the AI solution draft process.

💰 Cost estimation:

  • Model: GPT-5.5
  • Provider: OpenAI
  • Public pricing estimate: $31.863471

📊 Context and tokens usage:

  • 672.7K / 1.1M (64%) input tokens, 61.0K / 128K (48%) output tokens

Total: (672.7K + 22.4M cached) input tokens, 61.0K output tokens, $31.863471 cost

🤖 Models used:

  • Tool: OpenAI Codex
  • Requested: gpt-5.5
  • Model: GPT-5.5 (gpt-5.5)

📎 Log file uploaded as Repository (83153KB)


Now working session is ended, feel free to review and add any feedback on the solution draft.

@konard
Copy link
Copy Markdown
Contributor Author

konard commented May 12, 2026

✅ Ready to merge

This pull request is now ready to be merged:

  • All CI checks have passed
  • No merge conflicts
  • No pending changes

Monitored by hive-mind with --auto-restart-until-mergeable flag

@skulidropek
Copy link
Copy Markdown
Member

в Final build надо ещё проверить что запускается browser
И через менюшку у него работает клонирование проектов

@skulidropek
Copy link
Copy Markdown
Member

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 13, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 13, 2026

Review Change Stack

📝 Walkthrough

Summary by CodeRabbit

  • New Features

    • Added Final Build CI workflow providing cross-platform verification on Linux, macOS, and Windows.
  • Bug Fixes

    • Improved clone-cache mirror refresh to restrict fetching to branch and tag references only.
  • Chores

    • Enhanced build scripts for improved cross-platform compatibility.
    • Replaced platform-specific executable marking with a unified cross-platform approach.

Walkthrough

This PR establishes cross-platform support for Linux, macOS, and Windows by introducing portable executable marking, simplifying CLI scripts to remove bash wrappers, restricting git mirror refresh scope, and implementing a CI/CD workflow that validates the build across all three platforms.

Changes

Cross-platform build and CI pipeline

Layer / File(s) Summary
Cross-platform executable marking infrastructure
scripts/mark-executable.mjs, packages/docker-git-session-sync/package.json, packages/app/tests/docker-git/package-scripts-cross-platform.test.ts
New Bun-compatible script marks built CLI files executable on POSIX systems without using raw chmod. Session-sync build now uses this helper. Contract tests verify no bash or raw chmod references in launch and build scripts.
CLI script simplification across packages
package.json, packages/app/package.json
Root and app npm scripts remove bash -lc wrappers and $@ argument forwarding, replacing them with direct Bun invocation of the built CLI entrypoint for clone, open, docker-git, list, and start commands.
Clone-cache mirror refspec restrictions
packages/lib/src/core/templates-entrypoint/tasks.ts, packages/app/src/lib/core/templates-entrypoint/tasks.ts, packages/lib/tests/core/templates.test.ts
Both lib and app introduce cloneCacheRefreshRefspecs constants limiting git mirror refresh to refs/heads/* and refs/tags/* instead of broad refs/*. Tests verify the narrowed scope excludes forge PR and MR refs.
Cross-platform CI/CD final-build workflow
.github/workflows/final-build.yml, .github/actions/setup/action.yml, .changeset/cross-platform-final-build.md
New workflow builds across ubuntu-latest, macos-latest, and windows-latest with pinned Bun 1.3.11 and Node 24.14.0, performs smoke tests on both CLI tools, packs built packages into tarballs, and uploads OS-specific artifacts. Setup action conditionally installs OpenSSH only on Linux. Changeset documents portable scripts and CI verification.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 Across all the systems, from Windows to Linux so fair,
Our scripts now run portable, without any bash in the air!
Mark-executable marks files with cross-platform grace,
While CI builds validate from every OS place. 🚀

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main objective: adding a cross-platform CI workflow for final build checks across multiple operating systems.
Description check ✅ Passed The description provides comprehensive coverage including summary, verification approach with test evidence, local checks performed, and mathematical guarantees. It aligns well with the template requirements.
Linked Issues check ✅ Passed The PR fully addresses issue #278 requirements: implements a cross-platform CI/CD workflow (Final Build) for Linux, macOS, and Windows that runs the final build with end-to-end testing.
Out of Scope Changes check ✅ Passed All changes are directly related to the PR objectives: CI workflow setup, cross-platform script portability, clone-cache refspec bounds, and regression tests. No unrelated modifications are present.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/final-build.yml:
- Around line 27-33: The workflow .github/workflows/final-build.yml currently
only checks CLIs ("Verify docker-git CLI starts" and "Verify session sync CLI
starts"); add a new step after those that performs the requested browser/UI
clone smoke check by launching a headless browser and exercising the UI clone
path (open app served from the build, navigate to the clone UI/menu, trigger a
clone, and assert success). Name the step clearly (e.g., "Verify browser UI
clone smoke check") and implement it using your existing test runner or a
lightweight headless tool (Playwright/puppeteer or an npm script) so it starts
the built web app, runs the UI clone flow, and fails the job on error.

In `@packages/app/tests/docker-git/package-scripts-cross-platform.test.ts`:
- Around line 24-34: Add fast-check property-based assertions covering the same
invariants currently tested by the table-driven checks: the "no bash" invariant
for each launch script and the "no chmod" invariant for the package build
script. Use fast-check's fc.assert with an fc.property that generates indices or
script entries from the existing launchScripts array and validates that the
selected entry.script does not match /\bbash(?:\.exe)?\b/u (referencing
launchScripts and entry.scriptName/entry.packageName for contextual failure
messages), and another property that checks sessionSyncPackage.scripts.build
does not match /\bchmod\s+/u. Replace or augment the existing for-loop and
single expect with these fc.assert(fc.property(...)) calls so the test file
package-scripts-cross-platform.test.ts uses property-based testing for the
invariants.

In `@packages/lib/tests/core/templates.test.ts`:
- Around line 77-86: The test for "renderEntrypoint clone cache" is missing
negative assertions for pull-request and merge-request refspecs; update the spec
for the entrypoint returned by renderEntrypoint(makeTemplateConfig()) to assert
it does not contain the undesired refs by adding checks that entrypoint does not
contain "'+refs/pull/*:refs/pull/*'" and
"'+refs/merge-requests/*:refs/merge-requests/*'". Ensure you add these two
expect(...).not.toContain(...) assertions alongside the existing negative check
so the test prevents regressions.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: f798fdcc-08da-4eff-8545-a01201bd5aac

📥 Commits

Reviewing files that changed from the base of the PR and between 65c4f84 and a872a79.

📒 Files selected for processing (11)
  • .changeset/cross-platform-final-build.md
  • .github/actions/setup/action.yml
  • .github/workflows/final-build.yml
  • package.json
  • packages/app/package.json
  • packages/app/src/lib/core/templates-entrypoint/tasks.ts
  • packages/app/tests/docker-git/package-scripts-cross-platform.test.ts
  • packages/docker-git-session-sync/package.json
  • packages/lib/src/core/templates-entrypoint/tasks.ts
  • packages/lib/tests/core/templates.test.ts
  • scripts/mark-executable.mjs

Comment on lines +27 to +33
- name: Build final workspace packages
run: bun run build
- name: Verify docker-git CLI starts
run: bun ./packages/app/dist/src/docker-git/main.js --help
- name: Verify session sync CLI starts
run: bun ./packages/docker-git-session-sync/dist/docker-git-session-sync.js --help
- name: Prepare package artifacts directory
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Final Build is missing the requested browser/UI clone smoke check.

The workflow currently validates CLI startup only. It does not cover the reviewer-requested runtime path: browser launch and cloning via UI/menu, so the PR acceptance criteria in discussion remain partially unverified.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/final-build.yml around lines 27 - 33, The workflow
.github/workflows/final-build.yml currently only checks CLIs ("Verify docker-git
CLI starts" and "Verify session sync CLI starts"); add a new step after those
that performs the requested browser/UI clone smoke check by launching a headless
browser and exercising the UI clone path (open app served from the build,
navigate to the clone UI/menu, trigger a clone, and assert success). Name the
step clearly (e.g., "Verify browser UI clone smoke check") and implement it
using your existing test runner or a lightweight headless tool
(Playwright/puppeteer or an npm script) so it starts the built web app, runs the
UI clone flow, and fails the job on error.

Comment on lines +24 to +34
describe("package scripts cross-platform contract", () => {
it("keeps user-facing launch scripts independent from bash", () => {
for (const entry of launchScripts) {
expect(entry.script, `${entry.packageName}:${entry.scriptName}`).not.toMatch(/\bbash(?:\.exe)?\b/u)
}
})

it("keeps final package build independent from raw chmod", () => {
expect(sessionSyncPackage.scripts.build).not.toMatch(/\bchmod\s+/u)
})
})
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Add property-based assertions for script invariants.

This test is table-driven only; please add fast-check property tests for the bash/chmod invariants to satisfy the test policy for .test.ts files.

Proposed direction
+import fc from "fast-check"
...
+  it("bash-free launch scripts hold for all declared launch entries", () => {
+    fc.assert(
+      fc.property(fc.constantFrom(...launchScripts), (entry) => {
+        expect(entry.script).not.toMatch(/\bbash(?:\.exe)?\b/u)
+      })
+    )
+  })

As per coding guidelines "**/*.test.{ts,tsx}: Implement property-based testing using fast-check for mathematical properties and invariants."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/app/tests/docker-git/package-scripts-cross-platform.test.ts` around
lines 24 - 34, Add fast-check property-based assertions covering the same
invariants currently tested by the table-driven checks: the "no bash" invariant
for each launch script and the "no chmod" invariant for the package build
script. Use fast-check's fc.assert with an fc.property that generates indices or
script entries from the existing launchScripts array and validates that the
selected entry.script does not match /\bbash(?:\.exe)?\b/u (referencing
launchScripts and entry.scriptName/entry.packageName for contextual failure
messages), and another property that checks sessionSyncPackage.scripts.build
does not match /\bchmod\s+/u. Replace or augment the existing for-loop and
single expect with these fc.assert(fc.property(...)) calls so the test file
package-scripts-cross-platform.test.ts uses property-based testing for the
invariants.

Comment on lines +77 to +86
describe("renderEntrypoint clone cache", () => {
it("refreshes mirrors without broad remote refs", () => {
const entrypoint = renderEntrypoint(makeTemplateConfig())

expect(entrypoint).toContain("git --git-dir '$CACHE_REPO_DIR' fetch")
expect(entrypoint).toContain("'+refs/heads/*:refs/heads/*'")
expect(entrypoint).toContain("'+refs/tags/*:refs/tags/*'")
expect(entrypoint).not.toContain("'+refs/*:refs/*'")
})
})
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

What is the recommended way to run fast-check property-based tests in Vitest 4.1.5 (including TypeScript examples)?

💡 Result:

Recommended way: use fast-check through the dedicated Vitest connector package @fast-check/vitest, and run property-based “prop” tests via the connector’s enriched test/it APIs (e.g., test.prop / it.prop). This is the safest/simplest integration because the connector wires up Vitest-specific concerns like timeouts and lifecycle hooks. [1][2] Setup (TypeScript) 1) Install: - npm i -D vitest fast-check @fast-check/vitest [1] 2) Write property-based tests using @fast-check/vitest instead of importing test/it directly from vitest. The connector provides.prop variants for property inputs. Example: tuple (positional) notation ts // your-test.spec.ts import { test, expect, fc } from '@fast-check/vitest'; a function isSubstring(text: string, pattern: string) { return text.includes(pattern); } test.prop([fc.string(), fc.string(), fc.string()])( 'should detect substring', (a, b, c) => { const text = a + b + c; return expect(isSubstring(text, b)).toBe(true); }, ); Property inputs can be provided positionally with test.prop([arb1, arb2,...]). [1][2] Example: record (named) notation ts import { test, expect, fc } from '@fast-check/vitest'; function isSubstring(text: string, pattern: string) { return text.includes(pattern); } test.prop({ a: fc.string(), b: fc.string(), c: fc.string() })( 'should detect substring', ({ a, b, c }) => { const text = a + b + c; expect(isSubstring(text, b)).toBe(true); }, ); Record notation passes inputs as a named object to the predicate. [1][2] Reproducibility / replaying failures (seed) You can pass fast-check parameters (including a seed) to test.prop so failures are replayable. [2] Example (seeded run) ts import { test, expect, fc } from '@fast-check/vitest'; test.prop([fc.nat(), fc.nat()], { seed: 4242 })( 'should replay the test for the seed 4242', (a, b) => { expect(a + b === b + a).toBe(true); }, ); [2] How this relates to “fast” execution in Vitest 4.1.5 - The recommended approach is to delegate property-test orchestration to @fast-check/vitest; it takes care of Vitest integration details (timeouts and beforeEach/afterEach lifecycle wiring) so property predicates run correctly under Vitest’s execution model. [1][2] - For more extensive property testing, @fast-check/vitest supports a full property-based mode that repeatedly generates inputs to find edge cases. [2] Alternative (not recommended for Vitest): using fast-check directly fast-check itself works with any runner, but fast-check’s Vitest docs specifically recommend the connector as the “safest and simplest path” for Vitest integration, rather than using Vitest’s test/it directly. [1]

Citations:


🏁 Script executed:

# First, locate the test file and examine its content
find . -path "*/packages/lib/tests/core/templates.test.ts" -type f

Repository: ProverCoderAI/docker-git

Length of output: 112


🏁 Script executed:

# Check if file exists using git ls-files as fallback
git ls-files | grep -E "templates\.test\.ts"

Repository: ProverCoderAI/docker-git

Length of output: 110


🏁 Script executed:

# Search for templates test file more broadly
fd "templates.test.ts" --type f

Repository: ProverCoderAI/docker-git

Length of output: 110


🏁 Script executed:

# Look for the renderEntrypoint function
rg "renderEntrypoint" -t ts -t tsx -A 5 --max-count 20

Repository: ProverCoderAI/docker-git

Length of output: 96


🏁 Script executed:

# Check project dependencies for Vitest and fast-check
cat package.json | jq '.devDependencies | to_entries[] | select(.key | test("vitest|fast-check")) | "\(.key): \(.value)"'

Repository: ProverCoderAI/docker-git

Length of output: 50


🏁 Script executed:

# Search for existing fast-check usage in test files
fd ".test.ts" -o ".spec.ts" --type f -x rg "fast-check|fc\." {} --max-count 5

Repository: ProverCoderAI/docker-git

Length of output: 204


🏁 Script executed:

# Read the test file
cat -n packages/lib/tests/core/templates.test.ts | head -100

Repository: ProverCoderAI/docker-git

Length of output: 5439


🏁 Script executed:

# Search for renderEntrypoint function definition
rg "function renderEntrypoint|const renderEntrypoint|export.*renderEntrypoint" -A 10

Repository: ProverCoderAI/docker-git

Length of output: 50380


🏁 Script executed:

# Check package.json for dependencies
cat package.json | head -100

Repository: ProverCoderAI/docker-git

Length of output: 4503


🏁 Script executed:

# Look for fast-check imports or usage
rg "from.*fast-check|import.*fc\." --type ts

Repository: ProverCoderAI/docker-git

Length of output: 50


🏁 Script executed:

# Find renderCloneBody and git ref generation logic
rg "renderCloneBody|git.*fetch.*refs|refs/heads|refs/tags" -A 3 -B 2

Repository: ProverCoderAI/docker-git

Length of output: 17230


🏁 Script executed:

# Check if fast-check is mentioned anywhere in the codebase (even if not installed)
rg "fast-check|fc\." --type ts --max-count 10

Repository: ProverCoderAI/docker-git

Length of output: 50


🏁 Script executed:

# Look at the package.json for lib package specifically
cat packages/lib/package.json | head -150

Repository: ProverCoderAI/docker-git

Length of output: 3283


Add explicit negative assertions for merge-request and pull-request refs.

The test validates the clone-cache refspec invariant (documented in tasks.ts) but is incomplete. Add expect(entrypoint).not.toContain("'+refs/pull/*:refs/pull/*'") and expect(entrypoint).not.toContain("'+refs/merge-requests/*:refs/merge-requests/*'") to prevent regression if those refs are accidentally reintroduced.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/lib/tests/core/templates.test.ts` around lines 77 - 86, The test for
"renderEntrypoint clone cache" is missing negative assertions for pull-request
and merge-request refspecs; update the spec for the entrypoint returned by
renderEntrypoint(makeTemplateConfig()) to assert it does not contain the
undesired refs by adding checks that entrypoint does not contain
"'+refs/pull/*:refs/pull/*'" and
"'+refs/merge-requests/*:refs/merge-requests/*'". Ensure you add these two
expect(...).not.toContain(...) assertions alongside the existing negative check
so the test prevents regressions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Надо сделать что бы запускалось как на виндоус так и на линукс удобно.

2 participants